package com.kaigejava.demo3.actor;

/**
 * @BelongsProject: kaigejavastudy
 * @BelongsPackage: com.kaigejava.demo3.actor
 * @Author: kaigejava
 * @CreateTime: 2023-08-16  14:47
 * @Description: TODO
 * @Version: 1.0
 */
import akka.actor.AbstractActor;
import akka.actor.ActorRef;
import akka.actor.Props;
import com.kaigejava.demo2.messagedto.CalculateMessageDTO;
import com.kaigejava.demo2.messagedto.PrintMessageDTO;
import com.kaigejava.demo3.Rule;
import com.kaigejava.demo3.RuleMessageDTO;
import com.kaigejava.demo3.SetRulesMessage;
import com.kaigejava.demo3.message.AddMessage;
import com.kaigejava.demo3.message.ResultMessage;

import java.util.ArrayList;
import java.util.List;

public class CalculatorActor extends AbstractActor {
    private ActorRef printerActor;
    private ActorRef additionActor;
    private ActorRef subtractionActor;
    private ActorRef multiplicationActor;
    private ActorRef divisionActor;
    private List<Rule> rules;

    public CalculatorActor() {

        printerActor = getContext().getSystem().actorOf(Props.create(PrinterActor.class), "printerActor");
        additionActor = getContext().getSystem().actorOf(Props.create(AdditionActor.class), "additionActor");
        subtractionActor = getContext().getSystem().actorOf(Props.create(SubtractionActor.class), "subtractionActor");
        multiplicationActor = getContext().getSystem().actorOf(Props.create(MultiplicationActor.class), "multiplicationActor");
        divisionActor = getContext().getSystem().actorOf(Props.create(DivisionActor.class), "divisionActor");
        rules = new ArrayList<>();
    }

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .match(CalculateMessageDTO.class, this::calculate)
                .match(SetRulesMessage.class, this::setRules)
                .build();
    }

    private void calculate(CalculateMessageDTO message) {
        int result = message.getA() + message.getB();
        Rule rule = getMatchingRule(result);
        if (rule != null) {
            ActorRef targetActor = rule.getTargetActor();
            targetActor.tell(new RuleMessageDTO(rule, message.getA(), message.getB(), result), getSelf());
        } else {
            printerActor.tell(new PrintMessageDTO(result), getSelf());
        }
    }

    private Rule getMatchingRule(int result) {
        for (Rule rule : rules) {
            if (result >= rule.getStart() && result <= rule.getEnd()) {
                return rule;
            }
        }
        return null;
    }

    private void setRules(SetRulesMessage message) {
        rules = message.getRules();
    }
}
